package org.sbbs.base.jsf;

import static jakarta.faces.application.FacesMessage.SEVERITY_ERROR;
import lombok.extern.slf4j.Slf4j;
import org.primefaces.PrimeFaces;
import org.primefaces.model.DialogFrameworkOptions;

import java.io.Serializable;
import java.util.List;
import lombok.Data;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.model.TreeNode;
import org.sbbs.base.jpa.dao.BaseTreeRepo;
import org.sbbs.base.jpa.entity.BaseTreeEntity;
import org.sbbs.base.jpa.manager.BaseTreeManager;
import static org.sbbs.base.jpa.manager.BaseTreeManager.rootId;
import static org.sbbs.base.jsf.BaseTableMBean.addDetailMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.support.MessageSourceAccessor;

/**
 *
 * @author jenkins
 * @param <T>
 * @param <Id>
 * @param <R>
 * @param <M>
 */
@Slf4j
@Data
public abstract class BaseTreeMBean<T extends BaseTreeEntity, Id extends Serializable, R extends BaseTreeRepo, M extends BaseTreeManager> implements Serializable {

    @Autowired
    @Qualifier("sma")
    //这个类的定义方式是个学问呀 @important
    private MessageSourceAccessor sma;
    private M manager;
    private TreeNode<T> root;
    private List<T> childrens;
    private T editObj;
    private TreeNode<T> selectedNode;
    private String selectedNodeRowKey;

    public BaseTreeMBean(M m) {
        manager = m;
    }

    protected TreeNode initRoot() {
        T r = (T) manager.findById(BaseTreeManager.rootId);
        root = this.initNode(r);
        return root;
    }

    protected abstract TreeNode initNode(T r);

    public void onNodeSelect(NodeSelectEvent event) {

        T obj = (T) event.getTreeNode().getData();
        this.editObj = obj;
        this.childrens = manager.findChildren(obj);
        event.getTreeNode().getChildren();
        selectedNodeRowKey = event.getTreeNode().getRowKey();

//        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Selected", selectedNodeRowKey);
//        FacesContext.getCurrentInstance().addMessage(null, message);
    }

    public void newOpt(String form) throws InstantiationException, IllegalAccessException {
        this.editObj = (T) this.root.getData().getClass().newInstance();
        this.editObj.setPid(rootId);
        this.editObj.setParent(this.root.getData());
        this.editObj.setLevel(this.root.getData().getLevel() + 1);
        this.openDialog(form);
    }

    public void newOtherOpt(String form) throws InstantiationException, IllegalAccessException {
        T eo = this.selectedNode.getData();
        this.editObj = (T) this.editObj.getClass().newInstance();
        this.editObj.setPid(eo.getId());
        this.editObj.setParent(eo);
        this.editObj.setLevel(eo.getLevel() + 1);
        this.openDialog(form);
    }

    public void editOpt(String form) {
        this.openDialog(form);
    }

    public void openDialog(String form) {
        String outcome = null;
        DialogFrameworkOptions options = DialogFrameworkOptions.builder()
                .resizable(true)
                .draggable(true)
                .modal(true)
                .closeOnEscape(true)
                .maximizable(true)
                .minimizable(true)
                .fitViewport(true)
                .responsive(true)
                .blockScroll(false)
                // “explode”（爆炸效果）、“slide”（滑动效果）、“fade”
                .showEffect("fade")
                .hideEffect("explode")
                .contentWidth("1600")
                .contentHeight("800")
                .build();
        PrimeFaces.current().dialog().openDynamic(form, options, null);
    }

    public void closeDialog() {
        PrimeFaces.current().dialog().closeDynamic(this.editObj);
    }

    public void saveSortChange() {
        manager.updateChildrenSort(childrens);
        this.selectedNode.getChildren().clear();
        for (T c : childrens) {
          this.selectedNode.getChildren().addLast(this.initNode(c));
          
        }
        
//        this.initRoot();
//        this.root.setExpanded(true);
this.selectedNode.setExpanded(true);
    }

    public void save() {
        try {
            boolean isNew = editObj.getId() == null;
            manager.save(editObj);

            if (isNew) {
                this.addNewNode();
            } else {
                this.editNode();
            }
//            this.initRoot();
            PrimeFaces.current().dialog().closeDynamic(editObj);
        } catch (Exception e) {
            e.printStackTrace();
            addDetailMessage(e.getMessage(), SEVERITY_ERROR);

        }
    }

    /**
     * 父亲:root
     *  选择节点:可能有也可能没有,都取消选择
     *
     * 父亲:选择的节点
     */
    private void addNewNode() {
        TreeNode<T> p;
        if (this.editObj.getPid().equals(rootId)) {
            p = this.root;
        } else {
            p = this.selectedNode;
        }
        if (p != null) {
            p.setExpanded(true);
        }
        if (this.selectedNode != null) {
            selectedNode.setSelected(false);
        }
//        this.selectedNode.setSelected(false);
        TreeNode<T> n = this.initNode(editObj);
        n.setSelected(true);
        n.setParent(p);
        p.getChildren().add(n);
        log.info(p.toString());

    }

    private void editNode() {
        TreeNode<T> p = this.selectedNode.getParent();
        this.selectedNode.setParent(null);
        this.selectedNode.getChildren().clear();
        p.getChildren().remove(this.selectedNode);
        this.selectedNode = this.initNode(editObj);
        p.getChildren().add(this.selectedNode);
    }

//    public void delSingle() {
//        if (this.editObj != null) {
//            if (!this.editObj.isHasChildren()) {
//
//                try {
//                    manager.remove(editObj);
////                Object[] args = {singleSelected.getId()};
//                    TreeNode<T> p = this.selectedNode.getParent();
//                    selectedNode.getChildren().clear();
//                    selectedNode.getParent().getChildren().remove(selectedNode);
//                    selectedNode.setParent(null);
//
//                    selectedNode = p;
//                    selectedNode.setSelected(true);
////                    this.initRoot();
//                    addDetailMessage(sma.getMessage("delete.success"));
//                } catch (Exception e) {
//                    e.printStackTrace();
//                    addDetailMessage(sma.getMessage("delete.exception"), SEVERITY_ERROR);
//                }
//            } else {
//
//                addDetailMessage(sma.getMessage("delete.hasChildren"), SEVERITY_WARN);
//            }
//        } else {
//            addDetailMessage(sma.getMessage("delete.noselected"), SEVERITY_WARN);
//        }
//    }
}
